package com.sleepsocial.persistency.entity.user;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.annotations.Element;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.Key;
import com.sleepsocial.authentication.UserProfileException;
import com.sleepsocial.persistency.PMF;
import com.sleepsocial.persistency.entity.oauth.OauthUserProfile;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class UserProfile {

    @SuppressWarnings("unchecked")
    public static UserProfile getUserByEmail(String email) {
        Query q = PMF.getPersistenceManager().newQuery(UserProfile.class);
        q.setFilter("email == \"" + email + "\"");
        List<UserProfile> profiles = (List<UserProfile>) q.execute();
        if (profiles.size() > 0) {
            return profiles.get(0);
        } else {
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public static UserProfile storeOauthUserProfile(OauthUserProfile oauthProfile) {
        String email = oauthProfile.getEmail();
        PersistenceManager pm = PMF.getPersistenceManager();
        Query q = pm.newQuery(UserProfile.class);
        q.setFilter("email == '" + oauthProfile.getEmail() + "'");
        List<UserProfile> profiles = (List<UserProfile>) q.execute();
        UserProfile userProfile;
        if (profiles.size() == 0) {// There is no userProfile for this profile.
            userProfile = new UserProfile(email);
            pm.makePersistent(userProfile);

        } else {// There is already 1 Userprofile for the given email
            userProfile = profiles.get(0);
        }
        // Adds or update the userProfile
        userProfile.addOauthProfile(oauthProfile);
        return userProfile;
    }

    public static UserProfile storeUserProfile(String email, String passwordHash) throws UserProfileException {
        PersistenceManager pm = PMF.getPersistenceManager();
        if (getUserByEmail(email) != null) {
            throw new UserProfileException("An user for the given email [" + email + "] already exists");
        }
        UserProfile profile = new UserProfile(email);
        profile.setPasswordHash(passwordHash);
        pm.makePersistent(profile);
        return profile;
    }

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key                    key;

    @Persistent
    private String                 passwordHash;

    @Persistent
    private String                 email;

    @Persistent
    @Element(dependent = "true")
    private List<OauthUserProfile> profiles = new ArrayList<OauthUserProfile>();

    public UserProfile(String email) {
        this.setEmail(email);
    }

    public OauthUserProfile addOauthProfile(OauthUserProfile profile) {

        if (containsProfile(profile)) {
            return updateOauthProfile(profile);
        } else {
            if (profiles.add(profile)) {
                return profile;
            } else {
                return null;
            }
        }

    }

    public boolean containsProfile(OauthUserProfile profile) {
        Iterator<OauthUserProfile> it = profiles.iterator();
        while (it.hasNext()) {
            if (it.next().equals(profile)) {
                return true;
            }
        }
        return false;

    }

    public String getEmail() {
        return email;
    }

    public Key getKey() {
        return key;
    }

    public String getPasswordHash() {
        return passwordHash;
    }

    public List<OauthUserProfile> getProfiles() {
        return profiles;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPasswordHash(String passwordHash) {
        this.passwordHash = passwordHash;
    }

    public OauthUserProfile updateOauthProfile(OauthUserProfile profile) {
        // TODO enhance this
        return profiles.set(profiles.indexOf(profile), profile);

    }
}
